#include <Ogre.h>

#include "NetworkState.h"
#include "PlayState.h"
#include "IntroState.h"

using namespace Ogre;

NetworkState NetworkState::mNetworkState;

NetworkState::NetworkState() :
	mChatBox(0),
	spriteManager(0)
{
	mWindow = 0;
	mDebugOverlay = 0;
	displayCameraDetails = false;
	statsOn = false;
	mTimeUntilNextToggle = 0.0f;
}

void NetworkState::enter()
{
	mRoot = Root::getSingletonPtr();
	mWindow = mRoot->getAutoCreatedWindow();
	mDeviceManager = DeviceManager::getSingletonPtr();
	mDeviceManager->setBuffered(true);
	mGUIManager = GUIManager::getSingletonPtr();
	mKeyboard = mDeviceManager->mKeyboard;
	mMouse = mDeviceManager->mMouse;
	mChatBox = ChatBox::getSingletonPtr();
	mChatBox->clear();
	mChatBox->setFadeOn(false);

	// Set up Debug Overlay
	mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");

	// Create SceneManager	
	mSceneMgr = mRoot->getSceneManager("plitzScene");

	// Create Camera
	mCamera = mSceneMgr->createCamera("NetCamera");
	
	// Create Viewport
	mViewport = mRoot->getAutoCreatedWindow()->addViewport(mCamera);
	mViewport->setBackgroundColour(ColourValue(0.0, 0.0, 0.0));

	// Create Sprite Manager
	//spriteManager=new Ogre2dManager;
	//spriteManager->init(mSceneMgr, Ogre::RENDER_QUEUE_OVERLAY, true);

	// Reigster GUI Items
	CEGUI::WindowManager *wmgr = CEGUI::WindowManager::getSingletonPtr();
	mGUIManager->registerScene(mSceneMgr);
	mGUIManager->setGUISheet(CEGUI::WindowManager::getSingletonPtr()->getWindow("Net/Sheet"));
	mMapHolderOverlay = Ogre::OverlayManager::getSingletonPtr()->getByName("MapPreviewOverlay");

	// Init scrollbar pointers
	p1RedScroll = static_cast<CEGUI::Scrollbar*>(wmgr->getWindow((CEGUI::utf8*)"Net/P1RedSlider"));
	p1GrnScroll = static_cast<CEGUI::Scrollbar*>(wmgr->getWindow((CEGUI::utf8*)"Net/P1GrnSlider"));
	p1BluScroll = static_cast<CEGUI::Scrollbar*>(wmgr->getWindow((CEGUI::utf8*)"Net/P1BluSlider"));
	p2RedScroll = static_cast<CEGUI::Scrollbar*>(wmgr->getWindow((CEGUI::utf8*)"Net/P2RedSlider"));
	p2GrnScroll = static_cast<CEGUI::Scrollbar*>(wmgr->getWindow((CEGUI::utf8*)"Net/P2GrnSlider"));
	p2BluScroll = static_cast<CEGUI::Scrollbar*>(wmgr->getWindow((CEGUI::utf8*)"Net/P2BluSlider"));

	// Resets box
	CEGUI::Window *mapSelect = wmgr->getWindow((CEGUI::utf8*)"Net/MapSelect");
	mapSelect->setProperty("Text","Select Map");
	Config::LEVEL = "";
	mSpaceDockContainer = mMapHolderOverlay->getChild("MapSpaceDock");
	mStoneHengeContainer = mMapHolderOverlay->getChild("MapStoneHenge");
	mVSContainer = mMapHolderOverlay->getChild("MapVS");
	mMapHolderOverlay->show();

	// Reposition the chat box
	//mChatBox->setPosition(0.175f,0.64f);
	mChatBox->setPosition(0.330f,0.7f);
	mChatBox->addText("Choose a color for your character.");
	mChatBox->addText("     Select a map and play!");
	
	setupEventHandlers();

	// Set default values for each entry
	mGoBack = false;
	mStart = false;

	// Create Sound Manager
	soundManager = OgreAL::SoundManager::getSingletonPtr();
	
	createScene();

	// Playing music
	sound = soundManager->createSound("Others", "Others.ogg", true);
	sound->setGain(Config::BGSOUNDLEVEL);
	sound->play();
}

void NetworkState::exit()
{
	// Removing Game GUI
	mChatBox->clear();
	//spriteManager->end();
	//delete spriteManager;
	
	mMapHolderOverlay->hide();

	// Switch off debug overlays
	displayCameraDetails = false;
	statsOn = false;
	mDebugOverlay->hide();

	mSceneMgr->clearScene();
	mSceneMgr->destroyAllCameras();
	mRoot->getAutoCreatedWindow()->removeAllViewports();
	
	//Removing sound
	sound->stop();
	soundManager->destroySound(sound);
}

void NetworkState::pause()
{
}

void NetworkState::resume()
{
}

bool NetworkState::keyPressed(const OIS::KeyEvent &arg)
{
	if (arg.key == OIS::KC_S && Config::LEVEL != "")	// S to Start
		mStart = true;
	if (arg.key == OIS::KC_B || arg.key == OIS::KC_ESCAPE)	// B to Back
		mGoBack = true;

	// Toggle Debug Overlay
	if (arg.key == OIS::KC_F1 && mTimeUntilNextToggle <= 0 && Config::getInstance()->cfg_debugOn)
	{
		statsOn = !statsOn;
		mTimeUntilNextToggle = 0.5;
		if (statsOn) mDebugOverlay->show();
		else mDebugOverlay->hide();
	}

	// ChatBox keys
	/*if (arg.key == OIS::KC_Y && mTimeUntilNextToggle <= 0)
	{
		mChatBox->addText("You pressed the 'Y' Key in Net State.");
		mTimeUntilNextToggle = 0.3;
	}
	if (arg.key == OIS::KC_U && mTimeUntilNextToggle <= 0)
	{
		mChatBox->addText("You pressed the 'U' Key in Net State.");
		mTimeUntilNextToggle = 0.3;
	}*/

	return true;
}

bool NetworkState::keyReleased(const OIS::KeyEvent &arg)
{
	return true;
}

bool NetworkState::mouseMoved( const OIS::MouseEvent &arg )
{
	CEGUI::System::getSingleton().injectMouseMove( arg.state.X.rel, arg.state.Y.rel );
	mDeviceManager->mMouseCursor->updatePosition(arg.state.X.abs,arg.state.Y.abs);
	return true;
}

bool NetworkState::mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
	CEGUI::System::getSingleton().injectMouseButtonDown(convertOISMouseButtonToCegui(id));
	return true;
}

bool NetworkState::mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
	CEGUI::System::getSingleton().injectMouseButtonUp(convertOISMouseButtonToCegui(id));
	return true;
}

bool NetworkState::frameStarted(const FrameEvent& evt)
{
	// Update toggle buffering time
	if (mTimeUntilNextToggle >= 0)
				mTimeUntilNextToggle -= evt.timeSinceLastFrame;

	// Updating debug overlay stats
	updateStats();

	// Update chatbox
	mChatBox->loop(evt.timeSinceLastFrame);

	//drawSprites();

	// Update the preview map
	if (Config::LEVEL == "")
	{
		mVSContainer->show();
		mSpaceDockContainer->hide();
		mStoneHengeContainer->hide();
	}
	else if (Config::LEVEL == "SpaceDock.scene")
	{
		mVSContainer->hide();
		mSpaceDockContainer->show();
		mStoneHengeContainer->hide();
	}
	else if (Config::LEVEL == "stonehenge.scene")
	{
		mVSContainer->hide();
		mSpaceDockContainer->hide();
		mStoneHengeContainer->show();
	}
	
	// Rotate the model
	Ogre::Real rotAngle = evt.timeSinceLastFrame * 90;
	p1Avatar->setOrientation(p1Avatar->getOrientation()*Quaternion(Degree(rotAngle), Vector3::UNIT_Y));
	p2Avatar->setOrientation(p2Avatar->getOrientation()*Quaternion(Degree(-rotAngle), Vector3::UNIT_Y));

	if (mKeyboard) 
		mKeyboard->capture();
	if (mMouse)
		mMouse->capture();
	return true;
}

bool NetworkState::frameEnded(const FrameEvent& evt)
{
	if (mGoBack)
		changeState(IntroState::getInstance());
	if (mStart)
	{
		changeState(PlayState::getInstance());
	}
	return true;
}

void NetworkState::createScene()
{
	// Set up materials
	/*mapBlank = MaterialManager::getSingleton().getByName("PlitzBorder");
	
	Rectangle2D* rect = new Rectangle2D(true);
	double x1 = (0.0f-512.0f)/512.0f;
	double y1 = (384.0f-0.0f)/384.0f;
	double x2 = (1024.0f-512.0f)/512.0f;
	double y2 = (384.0f-768.0f)/384.0f;
	rect->setCorners(x1, y1, x2, y2);
	rect->setMaterial(mapBlank->getName());
	// Render the background before everything else
	rect->setRenderQueueGroup(RENDER_QUEUE_BACKGROUND);
	AxisAlignedBox aabInf;
	aabInf.setInfinite();
	rect->setBoundingBox(aabInf);
	// Attach background to the scene
	SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode("PlitzBorderNode");
	node->attachObject(rect);*/
	
	// Set up cameras
	mCamera->setNearClipDistance(0.1);
	mCamera->setFarClipDistance(1000);
	mCamera->setPosition(0, 50, -180);
	mCamera->lookAt(0, 30, -300);

	// Create models
	mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));
	Light* l = mSceneMgr->createLight("MainLight");
	l->setPosition(20,80,50);

	p1Mesh = mSceneMgr->createEntity("P1Avatar", "P1_Torso.mesh");
	p1Avatar = mSceneMgr->getRootSceneNode()->createChildSceneNode("P1AvatarNode",Vector3(-35, 25, -300));
	p1Avatar->attachObject(p1Mesh);

	p2Mesh = mSceneMgr->createEntity("P2Avatar", "P2_Torso.mesh");
	p2Avatar = mSceneMgr->getRootSceneNode()->createChildSceneNode("P2AvatarNode",Vector3(35, 25, -300));
	p2Avatar->attachObject(p2Mesh);
}

void NetworkState::setupEventHandlers()
{
	CEGUI::WindowManager *wmgr = CEGUI::WindowManager::getSingletonPtr();
	CEGUI::Window *start = wmgr->getWindow((CEGUI::utf8*)"Net/StartButton");
	start->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&NetworkState::handleStart, this));
    CEGUI::Window *back = wmgr->getWindow((CEGUI::utf8*)"Net/BackButton");
	back->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&NetworkState::handleBack, this));

	CEGUI::Window *mapSelect = wmgr->getWindow((CEGUI::utf8*)"Net/MapSelect");
	mapSelect->subscribeEvent(CEGUI::Combobox::EventListSelectionAccepted, 
				CEGUI::Event::Subscriber(&NetworkState::handleMapSelection, this));

	CEGUI::Window *p1Red = wmgr->getWindow((CEGUI::utf8*)"Net/P1RedSlider");
	p1Red->subscribeEvent(CEGUI::Scrollbar::EventScrollPositionChanged,CEGUI::Event::Subscriber(&NetworkState::handleP1ColourChanged, this));
	CEGUI::Window *p1Grn = wmgr->getWindow((CEGUI::utf8*)"Net/P1GrnSlider");
	p1Grn->subscribeEvent(CEGUI::Scrollbar::EventScrollPositionChanged,CEGUI::Event::Subscriber(&NetworkState::handleP1ColourChanged, this));
	CEGUI::Window *p1Blu = wmgr->getWindow((CEGUI::utf8*)"Net/P1BluSlider");
	p1Blu->subscribeEvent(CEGUI::Scrollbar::EventScrollPositionChanged,CEGUI::Event::Subscriber(&NetworkState::handleP1ColourChanged, this));

	CEGUI::Window *p2Red = wmgr->getWindow((CEGUI::utf8*)"Net/P2RedSlider");
	p2Red->subscribeEvent(CEGUI::Scrollbar::EventScrollPositionChanged,CEGUI::Event::Subscriber(&NetworkState::handleP2ColourChanged, this));
	CEGUI::Window *p2Grn = wmgr->getWindow((CEGUI::utf8*)"Net/P2GrnSlider");
	p2Grn->subscribeEvent(CEGUI::Scrollbar::EventScrollPositionChanged,CEGUI::Event::Subscriber(&NetworkState::handleP2ColourChanged, this));
	CEGUI::Window *p2Blu = wmgr->getWindow((CEGUI::utf8*)"Net/P2BluSlider");
	p2Blu->subscribeEvent(CEGUI::Scrollbar::EventScrollPositionChanged,CEGUI::Event::Subscriber(&NetworkState::handleP2ColourChanged, this));
}

bool NetworkState::handleP1ColourChanged(const CEGUI::EventArgs& e)
{
	Ogre::Real r = p1RedScroll->getScrollPosition() / 255.0f;
	Ogre::Real g = p1GrnScroll->getScrollPosition() / 255.0f;
	Ogre::Real b = p1BluScroll->getScrollPosition() / 255.0f;
	
	MaterialPtr mMaterial = MaterialPtr(MaterialManager::getSingleton().getByName("p1TorsoCol"));
	mMaterial->getTechnique(0)->getPass(0)->setDiffuse(r,g,b,1.0f);
	Config::P1COLOR = Ogre::ColourValue(r,g,b,1.0f);

	return true;

}

bool NetworkState::handleP2ColourChanged(const CEGUI::EventArgs& e)
{
	Ogre::Real r = p2RedScroll->getScrollPosition() / 255.0f;
	Ogre::Real g = p2GrnScroll->getScrollPosition() / 255.0f;
	Ogre::Real b = p2BluScroll->getScrollPosition() / 255.0f;
	
	MaterialPtr mMaterial = MaterialPtr(MaterialManager::getSingleton().getByName("p2TorsoCol"));
	mMaterial->getTechnique(0)->getPass(0)->setDiffuse(r,g,b,1.0f);
	Config::P2COLOR = Ogre::ColourValue(r,g,b,1.0f);

	return true;

}

bool NetworkState::handleBack(const CEGUI::EventArgs& e)
{
	mGoBack = true;
	return true;
}

bool NetworkState::handleStart(const CEGUI::EventArgs& e)
{
	if (Config::LEVEL == "")
	{
		mStart = false;//mChatBox->addText("Please select a map.");
	}
	else
	{
		mStart = true;
	}
	return true;
}

bool NetworkState::handleMapSelection(const CEGUI::EventArgs& e)
{
	const CEGUI::WindowEventArgs& windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>(e);
    CEGUI::ListboxItem* item = static_cast<CEGUI::Combobox*>(windowEventArgs.window)->getSelectedItem();
	switch(item->getID())
    {
        case 0:
			Config::getInstance()->LEVEL = "SpaceDock.scene";
			//mChatBox->addText("You selected SpaceDock map");
            break;
        case 1:
            Config::getInstance()->LEVEL = "stonehenge.scene"; //"SpaceDock.scene";
			//mChatBox->addText("You selected stonehenge map");
            break;
		default:
			Config::getInstance()->LEVEL = ""; //SpaceDock.scene
			break;
	};
	
	return true;
}

void NetworkState::drawSprites()
{
}